home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / dtype / mcsnd107.lha / Source / ScanResourceFile.c < prev    next >
C/C++ Source or Header  |  1994-09-03  |  8KB  |  306 lines

  1. /*
  2. **    MacSND DataType
  3. **
  4. **    Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  5. **        Public domain
  6. **
  7. ** :ts=4
  8. */
  9.  
  10. #include "Global.h"
  11.  
  12.     // We want to use the locals
  13.  
  14. #undef SysBase
  15. #define SysBase SysBase
  16.  
  17. #undef DOSBase
  18. #define DOSBase DOSBase
  19.  
  20.     // initCmd opcode controls
  21.  
  22. #define initMono            0x80    // A monophonic channel, please
  23. #define initStereo            0xC0    // Two stereo channels, please
  24.  
  25.     // Opcodes to replay sound
  26.  
  27. #define soundCmd            0x50    // Play a sound or a note
  28. #define bufferCmd            0x51    // Play a sound
  29.  
  30.     // Offset indicator
  31.  
  32. #define dataOffsetFlag        0x8000    // Data follows
  33.  
  34.     /* ReadMacBinaryHeader():
  35.      *
  36.      *    Read the MacBinary format header and seek to the
  37.      *    proper resource location
  38.      */
  39.  
  40. BOOL __regargs
  41. ReadMacBinaryHeader(BPTR Handle,LONG *Error,struct ExecBase *SysBase,struct DosLibrary *DOSBase)
  42. {
  43.     MacBinaryHeader Header;
  44.  
  45.         // No error so far
  46.  
  47.     *Error = 0;
  48.  
  49.         // Read the header, this should be 128 bytes
  50.  
  51.     if(FRead(Handle,&Header,sizeof(MacBinaryHeader),1) == 1)
  52.     {
  53.         LONG Offset;
  54.  
  55.             // The data is found at an odd address...
  56.  
  57.         CopyMem(Header . dflen,&Offset,sizeof(Offset));
  58.  
  59.             // Pad the offset to a multiple of 128, I suppose
  60.             // this is done in order to keep XModem happy
  61.  
  62.         Offset = 128 + ((Offset + 127) & ~127);
  63.  
  64.             // Seek to the resource data location
  65.  
  66.         if(Seek(Handle,Offset,OFFSET_BEGINNING) != -1)
  67.             return(TRUE);
  68.         else
  69.             *Error = ERROR_SEEK_ERROR;
  70.     }
  71.  
  72.         // No success
  73.  
  74.     return(FALSE);
  75. }
  76.  
  77.     /* ReadSoundHeader():
  78.      *
  79.      *    Fill in the BufferCmd data structure
  80.      */
  81.  
  82. BOOL __regargs
  83. ReadSoundHeader(BPTR Handle,LONG SoundResourceOffset,struct SoundDataHeader *SoundHeader,LONG *Error,struct ExecBase *SysBase,struct DosLibrary *DOSBase)
  84. {
  85.     WORD HeaderWords[2],NumCommands,i;
  86.  
  87.         // Read the two header words
  88.  
  89.     if(FRead(Handle,&HeaderWords,sizeof(HeaderWords),1) == 1)
  90.     {
  91.             // Is this a type 1 "snd " resource?
  92.  
  93.         if(HeaderWords[0] == 1)
  94.         {
  95.                 // How many synthesizer entries are there?
  96.  
  97.             if(HeaderWords[1])
  98.             {
  99.                 struct SynthHeader { WORD ID; LONG Init; } SynthHeader;
  100.  
  101.                     // Check all synthesizer init opcodes
  102.  
  103.                 for(i = 0 ; !(*Error) && i < HeaderWords[1] ; i++)
  104.                 {
  105.                         // Read the init header
  106.  
  107.                     if(FRead(Handle,&SynthHeader,sizeof(SynthHeader),1) == 1)
  108.                     {
  109.                             // Stereo sounds are not supported
  110.  
  111.                         if((SynthHeader . Init & 0xF0) == initStereo)
  112.                             return(FALSE);
  113.                     }
  114.                 }
  115.             }
  116.         }
  117.         else
  118.         {
  119.                 // Only type 1 and type 2 resources are supported
  120.  
  121.             if(HeaderWords[0] < 1 || HeaderWords[0] > 2)
  122.                 return(FALSE);
  123.         }
  124.  
  125.             // Read the number of commands to follow
  126.  
  127.         if(FRead(Handle,&NumCommands,sizeof(NumCommands),1) == 1)
  128.         {
  129.                 // Are there any commands following?
  130.  
  131.             if(NumCommands)
  132.             {
  133.                 struct SoundCommand { UWORD Command; WORD Param1; LONG Param2; } SoundCommand;
  134.  
  135.                     // Scan through the commands
  136.  
  137.                 for(i = 0 ; !(*Error) && i < NumCommands ; i++)
  138.                 {
  139.                         // Read the next command
  140.  
  141.                     if(FRead(Handle,&SoundCommand,sizeof(SoundCommand),1) == 1)
  142.                     {
  143.                             // Is this a soundCmd or bufferCmd and does it
  144.                             // have data following it?
  145.  
  146.                         if(SoundCommand . Command == (dataOffsetFlag | soundCmd) || SoundCommand . Command == (dataOffsetFlag | bufferCmd))
  147.                         {
  148.                                 // Seek to the bufferCmd header
  149.  
  150.                             if(Seek(Handle,SoundResourceOffset + SoundCommand . Param2,OFFSET_BEGINNING) != -1)
  151.                             {
  152.                                     // Read the sound header
  153.  
  154.                                 if(FRead(Handle,SoundHeader,sizeof(struct SoundDataHeader),1) == 1)
  155.                                 {
  156.                                         // Compressed sounds are not supported
  157.  
  158.                                     if(SoundHeader -> Encoding == stdSH)
  159.                                     {
  160.                                             // Seek to the location of the data
  161.  
  162.                                         if(Seek(Handle,SoundHeader -> DataOffset & 0x00FFFFFF,OFFSET_CURRENT) != -1)
  163.                                             return(TRUE);
  164.                                         else
  165.                                             *Error = ERROR_SEEK_ERROR;
  166.                                     }
  167.                                 }
  168.                                 else
  169.                                     *Error = IoErr();
  170.                             }
  171.                             else
  172.                                 *Error = ERROR_SEEK_ERROR;
  173.                         }
  174.                     }
  175.                     else
  176.                         *Error = IoErr();
  177.                 }
  178.             }
  179.         }
  180.         else
  181.             *Error = IoErr();
  182.     }
  183.     else
  184.         *Error = IoErr();
  185.  
  186.     return(FALSE);
  187. }
  188.  
  189.     /* ScanResource():
  190.      *
  191.      *    Scan a resource file for "snd " resources.
  192.      */
  193.  
  194. BOOL __regargs
  195. ScanResource(BPTR Handle,struct SoundDataHeader *SoundHeader,LONG *Error,struct ExecBase *SysBase,struct DosLibrary *DOSBase)
  196. {
  197.     struct ResourceHeader        ResourceHeader;
  198.     struct ResourceMapHeader    ResourceMapHeader;
  199.     struct ResourceTypeHeader    ResourceTypeHeader;
  200.     struct ResourceTypeEntry    ResourceTypeEntry;
  201.     struct ResourceReference    ResourceReference;
  202.     LONG                        Origin = Seek(Handle,0,OFFSET_CURRENT),i,j;
  203.  
  204.         // No error so far
  205.  
  206.     *Error = 0;
  207.  
  208.         // Read the resource header
  209.  
  210.     if(FRead(Handle,&ResourceHeader,sizeof(ResourceHeader),1) == 1)
  211.     {
  212.             // Seek to the resource map
  213.  
  214.         if(Seek(Handle,ResourceHeader . ResourceMapOffset + Origin,OFFSET_BEGINNING) != -1)
  215.         {
  216.                 // Read the resource map header
  217.  
  218.             if(FRead(Handle,&ResourceMapHeader,sizeof(ResourceMapHeader),1) == 1)
  219.             {
  220.                     // Both the first entries of the resource header and the
  221.                     // resource map header must match
  222.  
  223.                 if(!memcmp(&ResourceHeader,&ResourceMapHeader,4 * sizeof(LONG)))
  224.                 {
  225.                         // Seek to the resource type list
  226.  
  227.                     if(Seek(Handle,Origin + ResourceHeader . ResourceMapOffset + ResourceMapHeader . ResourceTypeListOffset,OFFSET_BEGINNING) != -1)
  228.                     {
  229.                             // Read the resource type list header
  230.  
  231.                         if(FRead(Handle,&ResourceTypeHeader,sizeof(ResourceTypeHeader),1) == 1)
  232.                         {
  233.                                 // Examine all entries
  234.  
  235.                             for(i = 0 ; !(*Error) && i <= ResourceTypeHeader . ResourceEntryCount ; i++)
  236.                             {
  237.                                     // Seek to an entry
  238.  
  239.                                 if(Seek(Handle,Origin + ResourceHeader . ResourceMapOffset + ResourceMapHeader . ResourceTypeListOffset + sizeof(struct ResourceTypeHeader) + i * sizeof(struct ResourceTypeEntry),OFFSET_BEGINNING) != -1)
  240.                                 {
  241.                                         // Read a resource type list entry
  242.  
  243.                                     if(FRead(Handle,&ResourceTypeEntry,sizeof(ResourceTypeEntry),1) == 1)
  244.                                     {
  245.                                             // Examine all resources of this type
  246.  
  247.                                         for(j = 0 ; !(*Error) && j <= ResourceTypeEntry . ResourceCount ; j++)
  248.                                         {
  249.                                                 // Seek to the resource reference
  250.  
  251.                                             if(Seek(Handle,Origin + ResourceHeader . ResourceMapOffset + ResourceMapHeader . ResourceTypeListOffset + ResourceTypeEntry . ResourceReferenceOffset + j * sizeof(struct ResourceReference),OFFSET_BEGINNING) != -1)
  252.                                             {
  253.                                                     // Read the resource reference header
  254.  
  255.                                                 if(FRead(Handle,&ResourceReference,sizeof(ResourceReference),1) == 1)
  256.                                                 {
  257.                                                         // Is this a "snd " type resource?
  258.  
  259.                                                     if(!memcmp(ResourceTypeEntry . ResourceType,"snd ",4))
  260.                                                     {
  261.                                                             // Seek to the corresponding resource data entry
  262.  
  263.                                                         if(Seek(Handle,Origin + ResourceMapHeader . ResourceDataOffset + (ResourceReference . ResourceInfo & 0xFFFFFF) + sizeof(LONG),OFFSET_BEGINNING) != -1)
  264.                                                         {
  265.                                                                 // Process the sound header
  266.  
  267.                                                             if(ReadSoundHeader(Handle,Origin + ResourceMapHeader . ResourceDataOffset + (ResourceReference . ResourceInfo & 0x00FFFFFF) + sizeof(LONG),SoundHeader,Error,SysBase,DOSBase))
  268.                                                                 return(TRUE);
  269.                                                         }
  270.                                                         else
  271.                                                             *Error = ERROR_SEEK_ERROR;
  272.                                                     }
  273.                                                 }
  274.                                                 else
  275.                                                     *Error = IoErr();
  276.                                             }
  277.                                             else
  278.                                                 *Error = ERROR_SEEK_ERROR;
  279.                                         }
  280.                                     }
  281.                                     else
  282.                                         *Error = IoErr();
  283.                                 }
  284.                                 else
  285.                                     *Error = ERROR_SEEK_ERROR;
  286.                             }
  287.                         }
  288.                         else
  289.                             *Error = IoErr();
  290.                     }
  291.                     else
  292.                         *Error = ERROR_SEEK_ERROR;
  293.                 }
  294.             }
  295.             else
  296.                 *Error = IoErr();
  297.         }
  298.         else
  299.             *Error = ERROR_SEEK_ERROR;
  300.     }
  301.     else
  302.         *Error = IoErr();
  303.  
  304.     return(FALSE);
  305. }
  306.